import 'dart:io';
import 'dart:math';

import 'package:device_info_plus/device_info_plus.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_keychain/flutter_keychain.dart';
import 'package:flutterflow_ui/flutterflow_ui.dart';
import 'package:get/get.dart';
import 'package:package_info_plus/package_info_plus.dart';

import '../r.dart';
import 'dd_user_service.dart';

class DDCustomRoute extends PageRouteBuilder {
  final Widget widget;

  DDCustomRoute(this.widget)
      : super(
            transitionDuration: Duration(milliseconds: 50),
            pageBuilder: (
              BuildContext context,
              Animation<double> animation1,
              Animation<double> animation2,
            ) {
              return widget;
            },
            transitionsBuilder: (
              BuildContext context,
              Animation<double> animation1,
              Animation<double> animation2,
              Widget child,
            ) {
              return FadeTransition(
                opacity: Tween(begin: 0.0, end: 1.0).animate(CurvedAnimation(
                  parent: animation1,
                  curve: Curves.fastOutSlowIn,
                )),
                child: child,
              );
            });
}

bool get isMobileDevice => !kIsWeb && (Platform.isIOS || Platform.isAndroid);

class DDAppInfo {
  // 15.3.1
  String systemVersion = '';
  // ios
  String systemName = '';
  // iPhone7,1
  String machine = '';
  // package
  String packageName = '';
  // 1.0.0
  String version = '';

  String buildNumber = '';
  // udid
  String? udid;

  String? token;

  String localLanguageCode = '';

  static DDAppInfo _instance = DDAppInfo();

  static DDAppInfo getInstance() {
    return _instance;
  }

  Future<DDAppInfo> init() async {
    if (isMobileDevice) {
      DeviceInfoPlugin deviceInfo = DeviceInfoPlugin();
      if (Platform.isIOS) {
        /// ios deviceInfo
        IosDeviceInfo iosInfo = await deviceInfo.iosInfo;
        // 12.3.1
        systemVersion = iosInfo.systemVersion;
        systemName = "iOS";
        // 例iPhone7,1
        machine = iosInfo.utsname.machine;
      }
      if (Platform.isAndroid) {
        /// androids deviceInfo
        AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo;
        systemVersion = androidInfo.version.release;
        systemName = "Android";
        machine = androidInfo.model;
        // final androidIdPlugin = AndroidId();
        // udid = await androidIdPlugin.getId() ?? '';
      }
    }

    udid = await getKeychainUDID() as String?;

    /// PackageInfo
    PackageInfo packageInfo = await PackageInfo.fromPlatform();

    packageName = packageInfo.packageName;

    version = packageInfo.version;

    buildNumber = packageInfo.buildNumber;

    localLanguageCode = Get.deviceLocale?.languageCode ?? '';
    return _instance;
  }

  Future<String?> getKeychainUDID() async {
    String? keychainUDID =
        await FlutterKeychain.get(key: "fencing_flutter_udid");
    if (keychainUDID == null || keychainUDID == "") {
      if (Platform.isIOS) {
        DeviceInfoPlugin deviceInfo = DeviceInfoPlugin();
        IosDeviceInfo iosInfo = await deviceInfo.iosInfo;
        keychainUDID = iosInfo.identifierForVendor;
      } else if (Platform.isAndroid) {
        // final androidIdPlugin = AndroidId();
        // keychainUDID = await androidIdPlugin.getId();
      } else {
        keychainUDID = "";
      }
      await FlutterKeychain.put(
          key: "fencing_flutter_udid", value: keychainUDID!);
    }
    return keychainUDID;
  }

  Future<String?> getAuthorizationToken() async {
    String? authorizationToken =
        await FlutterKeychain.get(key: "authorization_token");
    return authorizationToken;
  }

  Future<void> setAuthorizationToken(String token) async {
    await FlutterKeychain.put(key: "authorization_token", value: token);
  }

  Future<void> removeAuthorizationToken() async {
    await FlutterKeychain.remove(key: "authorization_token");
  }
}

String? getDataByName(List<dynamic> dataList, String name) {
  for (var item in dataList) {
    if (item['name'] == name) {
      return item['data'];
    }
  }
  return null;
}

extension DDStringExtensionNull on String? {
  // ignore: non_constant_identifier_names
  bool get dd_isEmpty => this == null || this!.isEmpty;
  // ignore: non_constant_identifier_names
  bool get dd_isNotEmpty => this != null && this!.isNotEmpty;
}

class DDPopAlert extends StatelessWidget {
  String? title;

  String? description;

  TextStyle? titleStyle;

  TextAlign? titleAlign;

  TextStyle? descriptionStyle;

  TextAlign? descriptionAlign;

  Widget? child;

  final String? childDescriptionGA;

  final bool dismissWhenOkBtnAction;

  final bool dismissWhenCancelBtnAction;

  final VoidCallback? okBtnAction;

  final VoidCallback? cancelBtnAction;

  final double? width;

  final double bgWidthSpace;

  final EdgeInsets contentInside;

  final double btnSpace;

  final String? screenName;

  final String? okTitle;
  final Widget? okChild;
  final String? cancelTitle;
  final Widget? cancelChild;
  final bool? showOkBtnArrow;
  final bool? showCancelBtnArrow;
  final double descriptionTopSpace;
  final double btnTopSpace;
  final double btnHeight;
  final double btnBorderRadius;
  final double bgBorderRadius;

  DDPopAlert.title({
    this.title = '',
    this.width,
    this.screenName,
    this.titleStyle,
    this.titleAlign,
    this.description,
    this.descriptionStyle,
    this.descriptionAlign,
    this.okTitle = '',
    this.cancelTitle = '',
    this.childDescriptionGA,
    this.okChild,
    this.cancelChild,
    this.showOkBtnArrow = false,
    this.showCancelBtnArrow = false,
    this.dismissWhenOkBtnAction = true,
    this.dismissWhenCancelBtnAction = true,
    this.okBtnAction,
    this.cancelBtnAction,
    this.descriptionTopSpace = 20,
    this.btnTopSpace = 0,
    this.btnHeight = 50.0,
    this.btnBorderRadius = 5.0,
    this.bgBorderRadius = 12.0,
    this.btnSpace = 0.5,
    this.bgWidthSpace = 60.0,
    this.contentInside =
        const EdgeInsets.only(right: 15, left: 15, top: 20, bottom: 20),
  });

  DDPopAlert.child(
    this.child, {
    this.width,
    this.screenName,
    this.okTitle = '',
    this.cancelTitle = '',
    this.okChild,
    this.cancelChild,
    this.childDescriptionGA,
    this.showOkBtnArrow = false,
    this.showCancelBtnArrow = false,
    this.dismissWhenOkBtnAction = true,
    this.dismissWhenCancelBtnAction = true,
    this.okBtnAction,
    this.cancelBtnAction,
    this.descriptionTopSpace = 20,
    this.btnTopSpace = 0,
    this.btnHeight = 50.0,
    this.btnBorderRadius = 5.0,
    this.bgBorderRadius = 6.0,
    this.btnSpace = 0.5,
    this.bgWidthSpace = 30.0,
    this.contentInside =
        const EdgeInsets.only(right: 15, left: 15, top: 20, bottom: 15),
  });

  @override
  Widget build(BuildContext context) {
    return WillPopScope(
      child: Center(
        child: Container(
          width: (context.orientation == Orientation.landscape
              ? 320
              : Get.width - bgWidthSpace * 2),
          decoration: BoxDecoration(
            color: Color(0xEDFFFFFF),
            borderRadius: BorderRadius.circular(bgBorderRadius),
          ),
          child: Column(
            mainAxisSize: MainAxisSize.min,
            children: <Widget>[
              Padding(
                padding: contentInside,
                child: child ??
                    Column(
                      mainAxisSize: MainAxisSize.min,
                      children: <Widget>[
                        child ??
                            Column(
                              children: <Widget>[
                                title.dd_isNotEmpty
                                    ? Text(
                                        title ?? '',
                                        style: titleStyle ??
                                            TextStyle(
                                              fontSize: 16,
                                              color: Color(0xFF004EA1),
                                            ),
                                        strutStyle:
                                            StrutStyle(forceStrutHeight: true),
                                        textAlign:
                                            titleAlign ?? TextAlign.center,
                                      )
                                    : SizedBox(),
                                title.dd_isNotEmpty
                                    ? SizedBox(height: descriptionTopSpace)
                                    : SizedBox(),
                                description.dd_isNotEmpty
                                    ? Text(
                                        description ?? '',
                                        style: descriptionStyle ??
                                            TextStyle(
                                              fontSize: 14,
                                              decoration: TextDecoration.none,
                                            ),
                                        textAlign: descriptionAlign ??
                                            TextAlign.center,
                                      )
                                    : SizedBox(height: 0)
                              ],
                            ),
                        description.dd_isNotEmpty
                            ? SizedBox(height: btnTopSpace)
                            : SizedBox(),
                      ],
                    ),
              ),
              Container(color: Colors.grey, height: 0.5),
              Row(
                mainAxisAlignment: MainAxisAlignment.center,
                children: <Widget>[
                  // cancel
                  cancelTitle.dd_isNotEmpty
                      ? Expanded(
                          child: CupertinoButton(
                            padding: EdgeInsets.zero,
                            child: cancelChild ??
                                Text(
                                  cancelTitle ?? '',
                                  textAlign: TextAlign.center,
                                  style: TextStyle(
                                    fontSize: 16,
                                    color: Color(0xFF666666),
                                  ),
                                ),
                            onPressed: () {
                              if (child == null) {
                              } else {
                                if (childDescriptionGA.dd_isNotEmpty) {}
                              }
                              if (dismissWhenCancelBtnAction &&
                                  navigator?.canPop() == true) {
                                navigator?.pop();
                              }
                              if (cancelBtnAction != null) {
                                cancelBtnAction!();
                              }
                            },
                          ),
                        )
                      : SizedBox(),
                  Container(
                    color: Colors.grey,
                    width:
                        (cancelTitle != null && okTitle != null) ? btnSpace : 0,
                    height: 50,
                  ),
                  // ok
                  okTitle.dd_isNotEmpty
                      ? Expanded(
                          child: CupertinoButton(
                            padding: EdgeInsets.zero,
                            child: okChild ??
                                Text(
                                  okTitle ?? '',
                                  textAlign: TextAlign.center,
                                  style: TextStyle(
                                    fontSize: 16,
                                    color: Color(0xFF004EA1),
                                  ),
                                ),
                            onPressed: () {
                              if (child == null) {
                              } else {
                                /// child description GA
                                if (childDescriptionGA.dd_isNotEmpty) {}
                              }
                              if (dismissWhenOkBtnAction &&
                                  navigator?.canPop() == true) {
                                navigator?.pop();
                              }
                              if (okBtnAction != null) {
                                okBtnAction!();
                              }
                            },
                          ),
                        )
                      : SizedBox(),
                ],
              ),
            ],
          ),
        ),
      ),
      onWillPop: () async {
        return false;
      },
    );
  }
}

class DDSafeButton extends StatelessWidget {
  final Widget? child;
  final VoidCallback? onPressed;
  final double minSize;
  final EdgeInsetsGeometry padding;
  final Duration time;
  final double pressedOpacity;

  const DDSafeButton({
    Key? key,
    this.child,
    this.onPressed,
    this.minSize = 0,
    this.padding = EdgeInsets.zero,
    this.pressedOpacity = 0.6,
    this.time = const Duration(milliseconds: 300),
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    bool canClicked = true;
    return CupertinoButton(
      padding: padding,
      minSize: minSize,
      pressedOpacity: pressedOpacity,
      child: child ?? SizedBox(),
      onPressed: onPressed != null
          ? () {
              if (canClicked && onPressed != null) {
                canClicked = false;
                Future.delayed(time, () {
                  canClicked = true;
                });
                if (onPressed != null) {
                  onPressed!();
                }
              }
            }
          : null,
    );
  }
}

class DDLoginSafeButton extends StatelessWidget {
  final Widget? child;
  final VoidCallback? onPressed;
  final double minSize;
  final EdgeInsetsGeometry padding;
  final Duration time;
  final double pressedOpacity;

  const DDLoginSafeButton({
    Key? key,
    this.child,
    this.onPressed,
    this.minSize = 0,
    this.padding = EdgeInsets.zero,
    this.pressedOpacity = 0.6,
    this.time = const Duration(milliseconds: 300),
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    bool canClicked = true;
    return CupertinoButton(
      // padding: padding,
      // minSize: minSize,
      // pressedOpacity: pressedOpacity,
      child: child ?? SizedBox(),
      onPressed: onPressed != null
          ? () {
              if (canClicked && onPressed != null) {
                canClicked = false;
                Future.delayed(time, () {
                  canClicked = true;
                });
                if (onPressed != null) {
                  onPressed!();
                }
              }
            }
          : null,
    );
  }
}

extension IntExtension on int {
  String to2tring() {
    return this.toString().padLeft(2, '0');
  }
}

extension DDContextExtension on BuildContext {
  static Map<int, Worker> workedMap = {};
  void didAppearCallBack(State state, VoidCallback didAppearCallBack) {
    if (this != null) {
      final appController = Get.find<AppService>();
      final worker = interval(
        appController.routeNameObs,
        (routeName) {
          if (state.mounted && this.findRenderObject()?.attached == true) {
            final route = ModalRoute.of(this);
            if (route?.settings.name == Get.routing.current) {
              didAppearCallBack();
            }
          }
        },
        time: Duration(milliseconds: 100),
      );
      DDContextExtension.workedMap[this.hashCode] = worker;
    }
  }

  void disposeWorker() {
    if (DDContextExtension.workedMap.containsKey(this.hashCode)) {
      final worked = DDContextExtension.workedMap[this.hashCode];
      if (worked != null) {
        worked.dispose();
      }
      DDContextExtension.workedMap.remove(this.hashCode);
    }
  }
}

String getBgStyle() {
  List<String> bgStyles = [
    R.assetsImagesBgA1,
    R.assetsImagesBgA2,
    R.assetsImagesBgA3,
    R.assetsImagesBgA4
  ];
  Random random = Random();
  int randomIndex = random.nextInt(bgStyles.length);
  String randomBgStyle = bgStyles[randomIndex];
  return randomBgStyle;
}

String getCurrentTimeAsId({int count = 1}) {
  DateTime now = DateTime.now();
  String formattedTime =
      "${now.year}${_twoDigits(now.month)}${_twoDigits(now.day)}${_twoDigits(now.hour)}${_twoDigits(now.minute)}${_twoDigits(now.second)}${count}";
  return formattedTime;
}

String getCurrentTime() {
  DateTime now = DateTime.now();
  String formattedTime = DateFormat.Hm().format(now);
  return formattedTime;
}

String _twoDigits(int n) {
  if (n >= 10) {
    return "$n";
  }
  return "0$n";
}

int randomNumber({int min = 5, int max = 20}) {
  Random random = Random();
  int randomNumber = min + random.nextInt(max - min + 1);
  return randomNumber;
}
